<template>
	<view :class="{popupShow:popupShow}">
		<u-transition :show="isDrag">
			<view id="_drag_button" class="drag" :style="'left: ' + left + 'px; top:' + top + 'px;'"
				@touchstart="touchstart" @touchmove.stop.prevent="touchmove" @touchend="touchend"
				@click.stop.prevent="click" :class="{transition: isDock && !isMove }">
				<image :src='imgOne' mode="scaleToFill"></image>
			</view>
		</u-transition>

		<u-popup catchtouchmove="ture" :overlayStyle="{'touch-action':'none'}" :show="isPopup" mode="center"
			@close="close" @open="open" :round="10" :safeAreaInsetBottom="false">
			<view class="popup-ai">
				<!-- 聊天栏顶部样式 -->
				<view class="exchange-top">
					<div class="top_menu">
						<div class="buttons">
							<div class="button close"></div>
							<div class="button minimize"></div>
							<div class="button maximize"></div>
						</div>
						<div class="title">讯飞星火大模型</div>
					</div>
				</view>
				<!-- 聊天栏内容区域 -->
				<!-- 超出高度显示下拉条 -->
				<view class="exchange-main">
					<view class="message-emypt" v-if="QAList.length ==0">

					</view>
					<!-- 消息数据窗口,高度不限制 -->
					<ul class="messages" v-else>
						<!-- bot -->
						<li class="message" v-for="item in QAList" :class="item.role === 'bot'? 'left':'right'">
							<view class="avatar">
								<img :src="item.avater">
							</view>
							<view class="text_wrapper" v-if="item.type === 'text'">
								<view class="text" v-html="item.text">
								</view>
							</view>
							<view class="text_wrapper audio_wrapper" @click="playAudio(item.audio.url)" v-else>
								<view class="text audioicon">
								</view>
								<view class="text audioicon">
								</view>
								<view class="text audioicon">
								</view>
								<view class="text audioicon">
								</view>
								<view class="text duration">
									<text>
										{{item.audio.duration}}
									</text>
								</view>
							</view>
						</li>
					</ul>
				</view>
				<!-- 聊天栏底部按钮区域 -->
				<!-- 语音按钮       输入框    发送按钮 -->
				<!--     语音    上拉取消发送 -->
				<!-- 语音录入动画 -->
				<u-transition :show="scale" mode="fade">
					<view class="musical-scale"
						:style="'background: '+ (sendLock ? 'rgba(225,87,62,0.4)':'rgba(0, 0, 0, 0.3)')">
						<view class="scale-mic">
							<!-- 音波图 -->
							<canvas type="2d" class="recwave-WaveView" style="width:75px;height:75px;"></canvas>
						</view>
						<text class="scale-tips">{{VoiceText}}</text>
					</view>
				</u-transition>
				<view class="exchange-btn">
					<view style="position: relative; height: 100%;">
						<!-- 语音 -->
						<u-transition :show="isAudio" mode="fade-up">
							<view class="audio row">
								<view class="col-view btn back">
									<u-button type="primary" :hairline="true" :plain="true" icon="arrow-left-double"
										@click="isAudio = false" :disabled="replyBtn"></u-button>
								</view>
								<view class="col-view mic">
									<view class="mic-btn" :class="replyBtn ? 'mic-disable':'' "
										@touchend="touchendAudio" @touchmove="handleTouchMoveAudio"
										@touchstart="longpressBtnAudio">
										<u-icon name="mic" color="white" size="24"></u-icon>
									</view>
								</view>
							</view>
						</u-transition>
						<!-- 文字 flex布局 -->
						<u-transition :show="!isAudio" mode="fade-up" duration="100">
							<view class="text row">
								<view class="col-view btn mic">
									<u-button type="primary" :hairline="true" :plain="true" icon="mic"
										@click="goAudio"></u-button>
								</view>
								<view class="col-view input">
									<u-input placeholder="请输入内容" border="surround" v-model="useInput">
										<template slot="suffix">
											<u-code start-text="发送" end-text="发送" ref="uCode" @change="inputChange"
												seconds="3" changeText="X秒后再点击"></u-code>
											<u-button @tap="getReply" :plain="true" :text="tips" type="success"
												size="small" :disabled="replyBtn"></u-button>
										</template>
									</u-input>
								</view>
							</view>
						</u-transition>
					</view>
				</view>
			</view>
		</u-popup>
	</view>
</template>

<script>
	// const recorderManager = uni.getRecorderManager()
	//必须引入的Recorder核心（文件路径是 /src/recorder-core.js 下同）
	import Recorder from 'recorder-core' //使用import、require都行

	//必须引入的RecordApp核心文件（文件路径是 /src/app-support/app.js）
	import RecordApp from 'recorder-core/src/app-support/app'

	//所有平台必须引入的uni-app支持文件（如果编译出现路径错误，请把@换成 ../../ 这种）
	import '@/uni_modules/Recorder-UniCore/app-uni-support.js'

	/** 需要编译成微信小程序时，引入微信小程序支持文件 **/
	// #ifdef MP-WEIXIN
	import 'recorder-core/src/app-support/app-miniProgram-wx-support.js'
	// #endif


	/** H5、小程序环境中：引入需要的格式编码器、可视化插件，App环境中在renderjs中引入 **/
	// #ifdef H5 || MP-WEIXIN
	//按需引入你需要的录音格式支持文件，如果需要多个格式支持，把这些格式的编码引擎js文件统统引入进来即可
	import 'recorder-core/src/engine/mp3'
	import 'recorder-core/src/engine/mp3-engine' //如果此格式有额外的编码引擎（*-engine.js）的话，必须要加上
	import 'recorder-core/src/engine/pcm'

	//可选的插件支持项
	import 'recorder-core/src/extensions/waveview'
	// #endif

	import { mapGetters } from "vuex";

	const file = uni.getFileSystemManager();

	const innerAudioContext = uni.createInnerAudioContext();

	import * as iatApi from '@/api/xfApi/iatManage.js'
	import * as xhApi from '@/api/xfApi/xhManage.js'
	import { pcmToMp3 } from '@/api/xfApi/ttsManage.js'

	// 导入 marked
	import marked from 'marked'

	export default {
		name: 'drag-button',
		computed: {
			...mapGetters(['user', 'AiFloatingWindow']), // 取出vuex中用户数据
		},
		props: {
			isDock: {
				type: Boolean,
				default: false
			},
			existTabBar: {
				type: Boolean,
				default: false
			},
		},

		data() {
			return {
				config: getApp().globalData.config, //全局获取
				top: 0,
				left: 0,
				width: 0,
				height: 0,
				offsetWidth: 0,
				offsetHeight: 0,
				windowWidth: 0,
				windowHeight: 0,
				isMove: true,
				edge: 10,
				value: 0,
				imgOne: require('@/static/assets/ai_drag.png'),
				isDrag: true,
				isPopup: false,
				useInput: '', // 用户输入框数据
				tips: '', // 提示
				QAList: [],
				isAudio: false, // 是否语音输入
				scale: false, // 当按住说话button时样式显示 or 隐藏
				startPoint: {}, //记录长按录音开始点信息,用于后面计算滑动距离。
				longPress: '1', // 1显示 按住 说话 2显示 说话中
				time: 0, //录音时长
				duration: 60000, //录音最大值ms 60000/1分钟
				sendLock: true, //发送锁，当为true时上锁，false时解锁发送
				VoiceText: '',
				lastRecord: '', // 播放的音频url
				waveView: null,
				replyBtn: false,
			}
		},
		mounted() {
			this.isMounted = true;
			const sys = uni.getSystemInfoSync();

			this.windowWidth = sys.windowWidth;
			this.windowHeight = sys.windowHeight;

			// #ifdef APP-PLUS
			this.existTabBar && (this.windowHeight -= 50);
			// #endif
			if (sys.windowTop) {
				this.windowHeight += sys.windowTop;
			}
			const query = uni.createSelectorQuery().in(this);
			query.select('#_drag_button').boundingClientRect(data => {
				this.width = data.width;
				this.height = data.height;
				this.offsetWidth = data.width / 2;
				this.offsetHeight = data.height / 2;
				this.left = this.windowWidth - this.width - this.edge;
				this.top = this.windowHeight - this.height - this.edge - 200;
			}).exec();

			// 音频处理
			//页面onShow时【必须调用】的函数，传入当前组件this
			RecordApp.UniPageOnShow(this);
		},
		onShow() { //onShow可能比mounted先执行，页面可能还未准备好
			if (this.isMounted) RecordApp.UniPageOnShow(this);
		},
		methods: {

			touchstart() {
				// this.$emit('btnTouchstart');
			},

			touchmove(e) {
				// 不是触摸球状态
				if (this.isPopup) {
					return false;
				}
				// 单指触摸
				if (e.touches.length !== 1) {
					return false;
				}
				this.isMove = true;
				this.left = e.touches[0].clientX - this.offsetWidth;
				let clientY = e.touches[0].clientY - this.offsetHeight;
				// #ifdef H5
				clientY += this.height;
				// #endif
				let edgeBottom = this.windowHeight - this.height - this.edge;

				// 上下触及边界
				if (clientY < this.edge) {
					this.top = this.edge;
				} else if (clientY > edgeBottom) {
					this.top = edgeBottom;
				} else {
					this.top = clientY
				}

			},

			touchend() {
				if (this.isDock) {
					let edgeRigth = this.windowWidth - this.width - this.edge;

					if (this.left < this.windowWidth / 2 - this.offsetWidth) {
						this.left = this.edge;
					} else {
						this.left = edgeRigth;
					}

				}
				this.isMove = false;
			},

			click() {
				console.log("触发点击AI界面事件");
				// 验证授权
				if (!this.user) {
					let isAuthorize = this.$store.dispatch("user/authorize");
					if (!isAuthorize) {
						return;
					}
				}
				this.$store.dispatch("app/toggleAiFloatingWindow");
				console.log("弹出后", this.AiFloatingWindow);
				this.isDrag = false;
				setTimeout(() => {
					this.isPopup = true;
					console.log("AI界面已出现");
				}, 200)
			},

			open() {
				// 打开触发事件
			},

			close() {
				this.isPopup = false;
				setTimeout(() => {
					this.$store.dispatch("app/toggleAiFloatingWindow");
					console.log("关闭后", this.AiFloatingWindow);
					this.isDrag = true;
					this.isAudio = false;
					this.useInput = '';
				}, 200)
			},

			inputChange(text) {
				this.tips = text;
			},
			// 文字回复
			getReply() {
				if (this.useInput.trim().length === 0 || this.useInput.trim() == null) {
					uni.showToast({
						title: "请输入内容~",
						icon: "none",
						duration: 1000
					});
					return;
				}
				if (this.$refs.uCode.canGetCode) {
					this.replyBtn = true;
					let question = {
						avater: this.user.avatarUrl,
						role: 'user',
						type: 'text',
						text: this.useInput
					}
					this.QAList.push(question)
					this.useInput = '';
					uni.showLoading({ title: '等待回复' })
					// 向后端请求
					xhApi.textReply({ question: question.text }).then(resp => {

						this.QAList.push({
							avater: require('@/static/bot.png'),
							role: 'bot',
							type: 'text',
							text: marked.parse(resp.data)
						})
						// console.log(this.QAList[this.QAList.length - 1]);
						uni.hideLoading();
						// 这里此提示会被this.start()方法中的提示覆盖
						// 通知验证码组件内部开始倒计时
						this.$refs.uCode.start();
						this.replyBtn = false;
					}).catch(() => {
						uni.hideLoading();
						this.replyBtn = false;
					})
				} else {
					uni.$u.toast('倒计时结束后再发送');
				}
			},
			goAudio() {
				// 获取是否授权信息
				this.recReq();
				// 显示语音输入界面
				this.isAudio = true
			},

			//请求录音权限
			recReq() {
				//编译成App时提供的授权许可（编译成H5、小程序为免费授权可不填写）；如果未填写授权许可，将会在App打开后第一次调用请求录音权限时，弹出“未获得商用授权时，App上仅供测试”提示框
				//RecordApp.UniAppUseLicense='我已获得UniAppID=*****的商用授权';

				RecordApp.UniWebViewActivate(this); //App环境下必须先切换成当前页面WebView
				RecordApp.RequestPermission(() => {
					console.log("已获得录音权限，可以开始录音了");
				}, (msg, isUserNotAllow) => {
					if (isUserNotAllow) { //用户拒绝了录音权限
						//这里你应当编写代码进行引导用户给录音权限，不同平台分别进行编写

					}
					console.error("请求录音权限失败：" + msg);
				});
			},
			// 松开录音事件
			touchendAudio() {
				this.longPress = '1';
				this.VoiceText = '';
				this.scale = false;
				RecordApp.Stop((arrayBuffer, duration, mime) => {
					//全平台通用：arrayBuffer是音频文件二进制数据，可以保存成文件或者发送给服务器
					//App中如果在Start参数中提供了stop_renderjs，renderjs中的函数会比这个函数先执行
					//注意：当Start时提供了takeoffEncodeChunk后，你需要自行实时保存录音文件数据，因此Stop时返回的arrayBuffer的长度将为0字节
					//如果当前环境支持Blob，也可以直接构造成Blob文件对象，和Recorder使用一致
					this.replyBtn = true;
					if (this.sendLock) {
						// 上锁
						console.log("因为上锁了所以就走这里");
						this.replyBtn = false;
					} else {
						if (duration < 1000) {
							uni.showToast({
								title: "录音时间太短",
								icon: "none",
								duration: 1000
							});
							this.replyBtn = false;
							console.log("时间还没到");
						} else if (duration > 60000) {
							this.replyBtn = false;
							uni.showToast({
								title: "录音时间太长拉",
								icon: "none",
								duration: 1000
							});
							console.log("时间太长了");
						} else {
							uni.showLoading({
								title: '等待回复'
							})
							// arrayBuffer转Base64文件流类型
							let base64String = encodeURIComponent(uni.arrayBufferToBase64(arrayBuffer));
							// 因微信小程序无法播放PCM格式音频,后端进行音频转换为MP3格式
							pcmToMp3({ base64String }).then(resp => {
								// console.log("434----------------------->获取到数据", resp);
								const fileName = 'temp_mp3_' + Date.now() + '.mp3' // 自定义文件名
								let filePath = wx.env.USER_DATA_PATH + "/" + fileName;
								let that = this;
								file.writeFile({
									filePath,
									data: resp,
									encoding: 'binary',
									success() {
										// 添加到问答队列中~
										that.QAList.push({
											avater: that.user.avatarUrl,
											role: 'user',
											type: 'audio',
											audio: {
												url: filePath,
												duration: (duration / 1000).toFixed(1)
											}
										})
									}
								})
							}).catch((err) => {
								console.log(err);
							})
							// 发送请求
							iatApi.textReply({ base64String }).then((resp) => {
								this.QAList.push({
									avater: 'http://s92ysmzou.hn-bkt.clouddn.com/assets/bot.png?e=1708307672&token=F5i2EAT0YlrOA9NvLbI3iFiPD-gdl9YMrQAp8O06:OL22tEqynt1A_qCZydxhsjmQCX0=',
									role: 'bot',
									type: 'text',
									text: marked.parse(resp.data)
								})
								uni.hideLoading();
								this.replyBtn = false;
							}).catch(() => {
								uni.hideLoading();
								this.replyBtn = false;
							})
						}
					}
				}, (msg) => {
					console.error("结束录音失败：" + msg);
				});

			},
			// 手指移动
			handleTouchMoveAudio(e) {
				var moveLenght = e.touches[e.touches.length - 1].clientY - this.startPoint.clientY; //移动距离
				if (Math.abs(moveLenght) > 70) { // 当偏移值大于70时，松开手指取消发送
					this.VoiceText = '松开手指,取消发送';
					this.sendLock = true; //触发了上滑取消发送，上锁
				} else {
					this.VoiceText = '松手结束录音';
					this.sendLock = false; //上划距离不足，依然可以发送，不上锁
				}
			},
			// 开始录制
			longpressBtnAudio(e) {
				this.startPoint = e.touches[0]; //记录长按时开始点信息，后面用于计算上划取消时手指滑动的距离。
				this.longPress = '2';
				this.VoiceText = '说话中...';

				//录音配置信息
				var set = {
					type: "pcm",
					sampleRate: 16000,
					bitRate: 16 //p格式，指定采样率hz、比特率kbps，其他参数使用默认配置；注意：是数字的参数必须提供数字，不要用字符串；需要使用的type类型，需提前把格式支持文件加载进来，比如使用wav格式需要提前加载wav.js编码引擎
						,
					onProcess: (buffers, powerLevel, duration, sampleRate, newBufferIdx, asyncEnd) => {
						//全平台通用：可实时上传（发送）数据，配合Recorder.SampleData方法，将buffers中的新数据连续的转换成pcm上传，或使用mock方法将新数据连续的转码成其他格式上传，可以参考Recorder文档里面的：Demo片段列表 -> 实时转码并上传-通用版；基于本功能可以做到：实时转发数据、实时保存数据、实时语音识别（ASR）等

						//注意：App里面是在renderjs中进行实际的音频格式编码操作，此处的buffers数据是renderjs实时转发过来的，修改此处的buffers数据不会改变renderjs中buffers，所以不会改变生成的音频文件，可在onProcess_renderjs中进行修改操作就没有此问题了；如需清理buffers内存，此处和onProcess_renderjs中均需要进行清理，H5、小程序中无此限制
						//注意：如果你要用只支持在浏览器中使用的Recorder扩展插件，App里面请在renderjs中引入此扩展插件，然后在onProcess_renderjs中调用这个插件；H5可直接在这里进行调用，小程序不支持这类插件；如果调用插件的逻辑比较复杂，建议封装成js文件，这样逻辑层、renderjs中直接import，不需要重复编写
						// console.log("buffers", buffers.length - 1, ",powerLevel", powerLevel);
						//H5、小程序等可视化图形绘制，直接运行在逻辑层；App里面需要在onProcess_renderjs中进行这些操作
						// #ifdef H5 || MP-WEIXIN
						if (this.waveView) {
							this.waveView.input(buffers[buffers.length - 1], powerLevel, sampleRate);
							// console.log(this.waveView);
						}
						// console.log("waveView", this.waveView);
						// #endif
					},
					onProcess_renderjs: `function(buffers,powerLevel,duration,sampleRate,newBufferIdx,asyncEnd){
				                //App中在这里修改buffers才会改变生成的音频文件
				                //App中是在renderjs中进行的可视化图形绘制，因此需要写在这里，this是renderjs模块的this（也可以用This变量）；如果代码比较复杂，请直接在renderjs的methods里面放个方法xxxFunc，这里直接使用this.xxxFunc(args)进行调用
				                if(this.waveView) this.waveView.input(buffers[buffers.length-1],powerLevel,sampleRate);
				            }`,
					takeoffEncodeChunk: true ? null : (chunkBytes) => {
						//全平台通用：实时接收到编码器编码出来的音频片段数据，chunkBytes是Uint8Array二进制数据，可以实时上传（发送）出去
						//App中如果未配置RecordApp.UniWithoutAppRenderjs时，建议提供此回调，因为录音结束后会将整个录音文件从renderjs传回逻辑层，由于uni-app的逻辑层和renderjs层数据交互性能实在太拉跨了，大点的文件传输会比较慢，提供此回调后可避免Stop时产生超大数据回传
					},
					takeoffEncodeChunk_renderjs: true ? null : `function(chunkBytes){
				                //App中这里可以做一些仅在renderjs中才生效的事情，不提供也行，this是renderjs模块的this（也可以用This变量）
				            }`,
					start_renderjs: `function(){
				                //App中可以放一个函数，在Start成功时renderjs中会先调用这里的代码，this是renderjs模块的this（也可以用This变量）
				                //放一些仅在renderjs中才生效的事情，比如初始化，不提供也行
				            }`,
					stop_renderjs: `function(arrayBuffer,duration,mime){
				                //App中可以放一个函数，在Stop成功时renderjs中会先调用这里的代码，this是renderjs模块的this（也可以用This变量）
				                //放一些仅在renderjs中才生效的事情，不提供也行
				            }`
				};

				RecordApp.UniWebViewActivate(this); //App环境下必须先切换成当前页面WebView
				RecordApp.Start(set, () => {
					this.scale = true;
					this.sendLock = false; //长按时是不上锁的。
					//创建音频可视化图形绘制，App环境下是在renderjs中绘制，H5、小程序等是在逻辑层中绘制，因此需要提供两段相同的代码
					//view里面放一个canvas，canvas需要指定宽高（下面style里指定了300*100）
					//<canvas type="2d" class="recwave-WaveView" style="width:300px;height:100px"></canvas>
					RecordApp.UniFindCanvas(this, [".recwave-WaveView"], `
				                this.waveView=Recorder.WaveView({compatibleCanvas:canvas1, width:300, height:100});
				            `, (canvas1) => {
						this.waveView = Recorder.WaveView({
							compatibleCanvas: canvas1,
							width: 300,
							height: 100
						});
					});
				}, (msg) => {
					console.error("开始录音失败：" + msg);
				});
			},
			// 点击播放
			playAudio(url) {
				console.log(url);
				if (url) {
					if (this.lastRecord == url && !innerAudioContext.paused) {
						innerAudioContext.stop(); // 停止
						return;
					}
					this.lastRecord = url; // 将路径赋值给定义的变量好做判断
					innerAudioContext.src = url; // 配置音频播放路径
					innerAudioContext.play(); // 播放
					innerAudioContext.autoplay = true
					innerAudioContext.volume = 0.3
					innerAudioContext.obeyMuteSwitch = false
				}

				// 解决IOS无法播放音频问题
				var music = wx.setInnerAudioOption({
					obeyMuteSwitch: false,
					success: function(res) {
						console.log("开启静音模式下播放音乐的功能");
					},
					fail: function(err) {
						console.log("静音设置失败");
					},
				});
			}
		}
	}
</script>

<style lang="scss">
	.drag {
		display: flex;
		justify-content: center;
		align-items: center;
		color: $uni-text-color-inverse;
		width: 100rpx;
		height: 100rpx;
		border-radius: 50%;
		font-size: $uni-font-size-sm;
		position: fixed;
		z-index: 999999;

		&.transition {
			transition: left .3s ease, top .3s ease;
		}

		image {
			width: 100%;
			height: 100%;
			box-sizing: border-box;
		}
	}

	.popup-ai {
		position: relative;
		width: 80vw;
		height: 60vh;
		border-radius: 10px;
		overflow: hidden;

		.exchange-top {
			.top_menu {
				background: var(--white);
				width: 100%;
				padding: 10px 0;
				height: 25px;
				box-shadow: 0 1px 30px rgba(0, 0, 0, 0.1);

				.title {
					text-align: center;
					color: var(--text-light);
					font-size: var(--font-size-medium);
				}

				.buttons {
					margin: 3px 0 0 20px;
					position: absolute;

					.button {
						width: 12px;
						height: 12px;
						border-radius: 50%;
						display: inline-block;
						margin-right: 5px;
						position: relative;
					}

					.close {
						background-color: var(--text-orange);
					}

					.minimize {
						background-color: var(--text-yellow);
					}

					.maximize {
						background-color: var(--text-blue);
					}
				}
			}
		}

		.exchange-main {
			height: calc(100% - 100px);
			overflow: scroll;
			overflow-x: hidden;
			box-sizing: border-box;

			.messages {
				position: relative;
				list-style: none;
				padding: 10px 5px 0 5px;
				margin: 0;

				.message {
					clear: both;
					overflow: hidden;
					margin-bottom: 20px;
					transition: all 0.5s linear;

					.avatar {
						width: 50px;
						height: 50px;
						border-radius: 50%;
						display: inline-block;

						img {
							max-width: 100%;
							max-height: 100%;
							border-radius: 50%;
						}
					}

					.text_wrapper {
						display: inline-block;
						padding: 20px;
						border-radius: 6px;
						width: calc(100% - 85px);
						min-width: 100px;
						position: relative;
						box-sizing: border-box;

						&::after,
						&::before {
							top: 18px;
							border: solid transparent;
							content: " ";
							height: 0;
							width: 0;
							position: absolute;
							pointer-events: none;
						}

						&::after {
							border-width: 13px;
							margin-top: 0px;
						}

						&::before {
							border-width: 15px;
							margin-top: -2px;
						}

						.text {
							font-size: var(--font-size-medium);
						}

					}

					.audio_wrapper {
						width: auto;
						padding: 15px 20px;

						.text {
							display: inline-block;
							position: relative;
							margin: 0 3px;
						}

						.audioicon {
							width: 3px;
							height: 12px;
							background: var(--white);

							&::before,
							&::after {
								content: " ";
								position: absolute;
								background: var(--white);
								width: 3px;
								height: 5px;
								border-radius: 50%;
							}

							&::before {
								top: -2px;
							}

							&::after {
								bottom: -2px;
							}
						}

						.duration {
							font-size: var(--font-size-small);
							font-weight: 700;
							color: var(--white) !important;

							&::before {
								content: ' "';
							}

							&::after {
								content: 's';
							}
						}
					}
				}

				.left {
					.avatar {
						background-color: var(--text-bg-blue);
						background-size: 100%;
						float: left;
					}

					.text_wrapper {
						background-color: var(--text-blue-light);
						margin-left: 20px;

						&::after,
						&::before {
							right: 100%;
							border-right-color: var(--text-blue-light);
						}

						.text {
							color: var(--text-blue);
						}
					}
				}

				.right {
					.avatar {
						background-color: var(--test-bg-green);
						float: right;
					}

					.text_wrapper {
						background-color: var(--text-green-light);
						margin-right: 20px;
						float: right;

						&::after,
						&::before {
							left: 100%;
							border-left-color: var(--text-green-light);
						}

						.text {
							color: var(--text-green);
						}
					}
				}


			}
		}

		.exchange-btn {
			height: 50px;
			padding-top: 5px;
			background-color: var(--white);
			border-radius: 3px;

			.audio {
				position: absolute;
				left: 0;
				right: 0;
				top: 0;
				bottom: 0;

				.col-view {
					padding: 0 5px;
					box-sizing: border-box;
				}

				.btn {
					// padding-top: 7px;
					padding-left: 10px;
					flex: 0 0 20%;
					max-width: 20%;

					::v-deep .u-button {
						width: 45px !important;
						height: 30px !important;
					}

				}

				.mic {
					flex: 0 0 80%;
					max-width: 80%;
					box-sizing: border-box;
					padding-right: 10px;

					.mic-btn {
						height: 40px;
						width: 100%;
						background: var(--text-blue);
						border-radius: 5px;
						display: flex;
						justify-content: center;

						&:hover {
							background: var(--click-active);
						}
					}

					.mic-disable {
						background: var(--click-active);
						pointer-events: none;
					}

				}

			}

			.text {
				position: absolute;
				left: 0;
				right: 0;
				top: 0;
				bottom: 0;

				.col-view {
					padding: 0 5px;
					box-sizing: border-box;
				}

				.btn {
					// padding-top: 7px;
					padding-left: 10px;
					flex: 0 0 20%;
					max-width: 20%;


					::v-deep .u-button {
						width: 45px !important;
						height: 30px !important;
					}
				}

				.input {
					padding-right: 10px;
					flex: 0 0 80%;
					max-width: 80%;
				}
			}
		}

		/* 录音时动画效果 */
		.musical-scale {
			position: absolute;
			left: 0;
			right: 0;
			top: 0;
			bottom: 0;
			margin: auto;
			height: 110px;
			width: 110px;
			padding: 5px;
			border: 1px solid rgba(0, 0, 0, 0.3);
			border-radius: 15px;
			text-align: center;
			transition: background-color .3s ease-in-out;

			.scale-mic {
				margin: auto;
				width: 75px;
				height: 75px;
				border-radius: 50%;
				border: 1px solid;
				border-color: var(--text-blue);
				display: flex;
				justify-content: center;
				align-items: center;
			}

			.scale-tips {
				margin-top: 5px;
				color: var(--white);
				font-size: var(--font-size-small);
			}

		}
	}
</style>